/** @ingroup uart
 * @file uart.h
 * @brief functions handling the uart communication
 *
 * @author cameris camerisdump@gmail.com
 */

#ifndef _UART_H_
#define _UART_H_

#include <stdint.h>

/** @name uart hardware settings
 * @{ */
#define UART_STATUS      UCSR0A
#define U2X_EN           U2X0

#define UART_CONTROL1    UCSR0B
#define UDRIE_EN         UDRIE0
#define RXCIE_EN         RXCIE0
#define RX_EN            RXEN0
#define TX_EN            TXEN0 
#define UART_TX_INT_VECT USART0_UDRE_vect
#define UART_RX_INT_VECT USART0_RX_vect

#define UART_CONTROL2    UCSR0C
#define PARITY_START     UPM00
#define STOPBIT          USBS0
#define DATABIT_START    UCSZ00

#define BAUD_HI          UBRR0H
#define BAUD_LO          UBRR0L

#define UART_DATA        UDR0
/**@} */

#define UART_TX_BUF_SIZE	16 /**< @brief transmit buffer size */
#define UART_RX_BUF_SIZE	128 /**< @brief receive buffer size */

#define UART_RX_FLOW_START	4 /**< @brief send XON when buffer reaches this size */

#if UART_RX_BUF_SIZE <= 128
#define UART_RX_FLOW_STOP	(UART_RX_BUF_SIZE / 2) /**< @brief send XOFF when buffer reaches this size */
#else
#define UART_RX_FLOW_STOP	(UART_RX_BUF_SIZE - 64)
#endif

/** @brief known baud rates */
enum {
	BAUD_2400,
	BAUD_4800,
	BAUD_9600,
	BAUD_19200,
	BAUD_38400,
	BAUD_57600,
	BAUD_115200,
	MAX_BAUD, /**< @brief indicates end of table */
};

/** @brief uart settings */
struct uart_para{
	uint8_t baud; /**< @brief baud index */
	unsigned int databits:2; /**< @brief data bits*/
	unsigned int parity:2; /**< @brief parity */
	unsigned int stopbits:1; /**< @brief stopbits */
};

void uart_init(void);
void uart_set_parameters(struct uart_para *para);
void uart_inc_baud(struct uart_para *para);
void uart_dec_baud(struct uart_para *para);
void uart_next_databits(struct uart_para *para);
void uart_next_parity(struct uart_para *para);
void uart_toggle_stopbits(struct uart_para *para);

void uart_send_string(uint8_t *str);
void uart_send_byte(uint8_t data);
void uart_send_string(uint8_t *s);
void uart_stop_receive(void);
void uart_start_receive(void);
uint8_t uart_get_byte(void);
uint8_t uart_byte_is_valid(void);
void uart_put_recv_byte(uint8_t byte);
#endif
